/**
* @package Scribble
*/
$(document).ready(function() {
	ModelBinder.init();
});

var ModelBinder = {

	/**
	* Cache of loaded server data.
	*
	* @var object
	*/
	cache: {},

	/**
	* Configuration store.
	*
	* @var object
	*/
	config: {
		callback: null,
		data: {
			models: []
		},
		pn: 1,
		targetModel: null
	},

	/**
	* URL from which media asset lists will be loaded.
	*
	* @var string
	*/
	feedUrl: '',

	/**
	* Sends info about the chosen assets back to the opener via the callback
	* function. It does NOT close the popup - it leaves it up to the callback
	* function in case it wants to run validation checks prior to closing.
	*
	* @return void
	*/
	complete: function() {
		ModelBinder.config.callback('complete', ModelBinder, ModelBinder.config.data);
	},

	/**
	* Initialise the view.
	*
	* @return void
	*/
	init: function() {

		// Grab configuration variables from "#config" hidden field which contains a
		// JSON encoded version of the config
		var configField = $('#config');
		if(configField.size()==0) {
			$('#view').html('<p>No configuration data has been specified. Cannot continue.</p>');
			return;
		}
		else {
			ModelBinder.config = $.extend({}, ModelBinder.config, $.evalJSON(configField.val()));
			$('#view').html('');
		}

		// Check callback has been defined
		var callback = top[ModelBinder.config.callback] ? top[ModelBinder.config.callback] : (
			window.opener && window.opener[ModelBinder.config.callback] ? window.opener[ModelBinder.config.callback] : null
		);
		if(callback===null) {
			$('#view').html('<p>The callback function is either undefined or does not exist. Cannot continue.</p>');
			return;
		}
		else {
			ModelBinder.config.callback = callback;
		}

		// JSON-decode data
		if(ModelBinder.config.data=='') {
			ModelBinder.config.data = [];
		}
		else {
			ModelBinder.config.data = $.evalJSON(ModelBinder.config.data);
		}

		// Get current page number
		ModelBinder.config.pn = Math.max(1, parseInt(ModelBinder.config.pn));

		// Setup the feed url
		ModelBinder.feedUrl = Buan.UrlCommand.createUrl('scribble', 'model-binding', 'browser-widget', ModelBinder.config);

		// "OK" button handler
		$('#btn-complete').click(ModelBinder.complete);

		// Load initial page of models and render any existing selections
		ModelBinder.load();
		ModelBinder.renderSelection();
	},

	/**
	* Loads a list of models from the server, and caches result.
	* The response will include the following elements:
	* - A list of models
	* - The no. pages of results available
	*
	* @param int Page to load (beginning at 1)
	* @return void
	*/
	load: function(pn) {

		// Check page number
		if(arguments.length==0 || pn<1) {
			pn = 1;
		}

		// Consult cache
		if(ModelBinder.cache[pn]) {
			ModelBinder.renderView(ModelBinder.cache[pn]);
			return;
		}

		// Load indicators
		$('#view').html('');

		// Request
		$.post(ModelBinder.feedUrl, {method:'load', pn:pn}, function(feed) {

			// Check error code
			if(feed.errorCode!==0) {
				alert(feed.errorMessage+'[code: '+feed.errorCode+']');
				return;
			}

			// Cache and render view
			ModelBinder.config.pn = pn;
			ModelBinder.cache[pn] = feed;
			ModelBinder.renderView(feed);
		}, 'json');
	},

	/**
	* Remove model from the selections list.
	*
	* @param sintr Model ID
	* @return void
	*/
	removeModel: function(id) {
		var models = [];
		for(var i=0; i<ModelBinder.config.data.models.length; i++) {
			var model = ModelBinder.config.data.models[i];
			if(model.id!==id) {
				models.push(model);
			}
		}
		ModelBinder.config.data.models = models;
		ModelBinder.renderSelection();
	},

	/**
	* This handler is bound to the "click" event on all links in the selection
	* container.
	*
	* @return false
	*/
	removeSelectionLink: function() {

		// Remove file
		ModelBinder.removeModel($(this).attr('model-id'));
		return false;
	},

	/**
	* Renders the list of selected assets.
	*
	* @return void
	*/
	renderSelection: function() {
		var container = $('#selection');
		var ul = $('<ul></ul>');
		for(var i=0; i<ModelBinder.config.data.models.length; i++) {
			var model = ModelBinder.config.data.models[i];
			var li = $('<li><a href="#"></a></li>');
			li.children('a').html(model.name).attr('model-id', model.id).click(ModelBinder.removeSelectionLink);
			ul.append(li);
		}
		container.html('').append(ul);
	},

	/**
	* Render the view using the given data.
	*
	* @param object Data, as it appears in the cache
	* @return void
	*/
	renderView: function(data) {

		// Render view in a list format
		$('#view').html('');
		ModelBinder.renderViewList(data);
	},

	/**
	* Render assets as a list
	*
	* @param object Asset data
	* @return void
	*/
	renderViewList: function(data) {

		// Build table
		var table = $('<table><thead><tr><th class="col-name">Name</th></tr></thead><tbody></tbody></table>');
		var tbody = table.children('tbody');

		for(var i in data.assets) {
			var asset = data.assets[i];
			var tr = $('<tr class="model" rel="asset"><td class="col-name"><a href="#"></a></td></tr>');
			tr.children('td.col-name').children('a').data('model', asset).html(asset.name).click(ModelBinder.selectAssetLink);
			tbody.append(tr);
		}

		$('#view').append(table);
	},

	/**
	* This handler is bound to the "click" event on all asset links in the view.
	*
	* @return bool
	*/
	selectAssetLink: function() {

		// Get info about the link
		var link = $(this);
		var modelData = link.data('model');

		// Select the asset
		ModelBinder.selectModel(modelData);

		// Prevent bubbling
		return false;
	},

	/**
	* Adds the specified model to the list of selections.
	*
	* @param Object Model data
	* @return void
	*/
	selectModel: function(model) {
		ModelBinder.config.data.models.push(model);
		ModelBinder.renderSelection();
	}
}